package appClientModule;

import java.net.*;
import java.io.*;
import java.awt.*;

/**
 * Player Class
 * 
 * @author Sam Cavenagh
 * @version 13/11/02
 * 
 *          Website: http://home.pacific.net.au/~cavenagh/SH/ Email:
 *          cavenaghweb@hotmail.com
 */
class Player {

	// used for testing makes deck empty at start of game if true
	boolean fastgame = false;

	// you must play less than a seven if true
	boolean seven = false;

	// if nine is invisible
	boolean nine = false;

	// if can swap cards at start of game
	boolean swap = false;
	boolean swapdone = false;

	boolean burnt = false;

	Socket msgSocket;
	PrintWriter out;
	BufferedReader in;

	SHinterface sh;

	Image cardspic;
	Image back;
	Image backSW;
	Image burntPic;
	Image pointer[];

	Hand hand;

	Graphics g;

	String playersName;

	// Details of other players
	String othernames[] = new String[3];
	Card faceup[][] = new Card[3][3];
	int carddowncount[] = new int[3];
	int cardcount[] = new int[3];
	Point tableposition[][] = new Point[3][3];

	Point centre1;// point where pile cards are displayed

	int deck; // count of card remaining in deck;

	Card pile[] = new Card[52]; // cards in play pile;

	boolean listen = true;// is thread listening for msg

	// for whos turn indicator
	String servername;
	int whosturn = 0;
	boolean outofgame[] = new boolean[4];
	Point pointerpoints[] = new Point[4];

	Score score; // scoreboard
	int position = 1;

	Player(SHinterface sh, Image cardspic, Graphics g, Hand hand, Image back,
			Image backSW, Image burntPic, Image[] pointer, Score score) {
		this.sh = sh;
		this.cardspic = cardspic;
		this.g = g;
		this.hand = hand;
		this.back = back;
		this.backSW = backSW;
		this.burntPic = burntPic;
		this.pointer = pointer;
		this.score = score;

		tableposition[0][0] = new Point(0, 103);
		tableposition[0][1] = new Point(0, 188);
		tableposition[0][2] = new Point(0, 276);

		tableposition[1][0] = new Point(103, 0);
		tableposition[1][1] = new Point(188, 0);
		tableposition[1][2] = new Point(276, 0);

		tableposition[2][0] = new Point(354, 103);
		tableposition[2][1] = new Point(354, 188);
		tableposition[2][2] = new Point(354, 276);

		centre1 = new Point(188, 175);

		outofgame[0] = false;
		outofgame[1] = false;
		outofgame[2] = false;
		outofgame[3] = false;

		pointerpoints[0] = new Point(115, 220);
		pointerpoints[1] = new Point(220, 110);
		pointerpoints[2] = new Point(330, 220);
		pointerpoints[3] = new Point(220, 330);
	}

	public void createConnection(String servername, String playersName) {
		this.playersName = playersName;
		score.addName(playersName);
		sh.addMsg("Looking for " + servername + " Dealer");
		try {
			msgSocket = new Socket(servername, 4445);
			out = new PrintWriter(msgSocket.getOutputStream(), true);
			in = new BufferedReader(new InputStreamReader(
					msgSocket.getInputStream()));
		} catch (UnknownHostException e) {
			sh.addMsg("Server: " + servername + " Could not be Found");
			sh.closeConnection();
		} catch (IOException e2) {
			sh.addMsg("Server not Listening for Connections");
		}

		if (msgSocket != null) {
			out.println(playersName);
			String name = "unknown#$#";
			String fastgameS = "false";
			String sevenS = "false";
			String nineS = "false";
			String swapS = "false";
			try {
				name = in.readLine();
				fastgameS = in.readLine();
				sevenS = in.readLine();
				nineS = in.readLine();
				swapS = in.readLine();
			} catch (IOException e3) {
				sh.addMsg("Getting Otherplayers Name Error " + e3);
			}

			if (!name.equals("unknown#$#")) {
				sh.addMsg("Game Connection Established with " + name);
				this.servername = name;
				// score.addName(servername);//added later ??
				if (fastgameS.equals("true")) {
					fastgame = true;
					sh.addMsg("Fast Game Selected");
				}

				if (sevenS.equals("true")) {
					seven = true;
					sh.addMsg("Must Play Under Seven Selected");
				}

				if (nineS.equals("true")) {
					nine = true;
					sh.addMsg("Nine is Invisible Selected");
				}

				if (swapS.equals("true")) {
					swap = true;
					sh.addMsg("Card Swap at start of game Selected");
				}
				listen = true;
				new WaitforMsg();
			}
		}
	}

	public void sendCommand(String command) {
		out.println(command);
	}

	private boolean fourOfAKind(Card card) {
		if (pile[0] == null || pile[1] == null || pile[2] == null
				|| card == null)
			return false;
		int top = pile[0].getValue();
		if (pile[1].getValue() == top && pile[2].getValue() == top
				&& card.getValue() == top)
			return true;
		return false;
	}

	public void endConnection() {
		listen = false;

		if (msgSocket != null) {
			out.println("end:");
			try {
				msgSocket.close();
			} catch (IOException e) {
			}
		}

		sh.addMsg("Game Connection Closed");
	}

	private void nextTurn() {
		whosturn++;
		if (whosturn >= 4)
			whosturn = 0;
		while (outofgame[whosturn]) {
			whosturn++;
			if (whosturn >= 4)
				whosturn = 0;
		}
	}

	public void displayTable() {
		g.setColor(Color.black);
		g.fillRect(0, 0, 450, 550);
		g.setColor(Color.white);
		g.drawLine(0, 450, 450, 450);
		g.setColor(Color.red);
		g.drawRoundRect(355, 5, 90, 40, 15, 15);
		g.setColor(Color.white);
		g.drawString("Deck: " + deck, 365, 20);
		g.drawString("Pile: " + pilelength(), 365, 40);
		hand.showHand();

		g.drawRoundRect(5, 360, 90, 40, 15, 15);
		g.drawString("Name: " + othernames[0], 10, 375);
		g.drawString("Cards: " + cardcount[0], 10, 395);
		g.drawImage(pointer[1], 68, 380, sh);
		if (faceup[0][0] != null)
			faceup[0][0].drawSideWays(tableposition[0][0]);
		else if (carddowncount[0] >= 3)
			g.drawImage(backSW, (int) tableposition[0][0].getX(),
					(int) tableposition[0][0].getY(), sh);
		if (faceup[0][1] != null)
			faceup[0][1].drawSideWays(tableposition[0][1]);
		else if (carddowncount[0] >= 2)
			g.drawImage(backSW, (int) tableposition[0][1].getX(),
					(int) tableposition[0][1].getY(), sh);
		if (faceup[0][2] != null)
			faceup[0][2].drawSideWays(tableposition[0][2]);
		else if (carddowncount[0] >= 1)
			g.drawImage(backSW, (int) tableposition[0][2].getX(),
					(int) tableposition[0][2].getY(), sh);

		g.drawRoundRect(5, 5, 90, 40, 15, 15);
		g.drawString("Name: " + othernames[1], 10, 20);
		g.drawString("Cards: " + cardcount[1], 10, 40);
		g.drawImage(pointer[2], 70, 25, sh);
		if (faceup[1][0] != null)
			faceup[1][0].drawCard(tableposition[1][0]);
		else if (carddowncount[1] >= 3)
			g.drawImage(back, (int) tableposition[1][0].getX(),
					(int) tableposition[1][0].getY(), sh);
		if (faceup[1][1] != null)
			faceup[1][1].drawCard(tableposition[1][1]);
		else if (carddowncount[1] >= 2)
			g.drawImage(back, (int) tableposition[1][1].getX(),
					(int) tableposition[1][1].getY(), sh);
		if (faceup[1][2] != null)
			faceup[1][2].drawCard(tableposition[1][2]);
		else if (carddowncount[1] >= 1)
			g.drawImage(back, (int) tableposition[1][2].getX(),
					(int) tableposition[1][2].getY(), sh);

		g.drawRoundRect(355, 360, 90, 40, 15, 15);
		g.drawString("Name: " + othernames[2], 360, 375);
		g.drawString("Cards: " + cardcount[2], 360, 395);
		g.drawImage(pointer[1], 423, 380, sh);
		if (faceup[2][0] != null)
			faceup[2][0].drawSideWays(tableposition[2][0]);
		else if (carddowncount[2] >= 3)
			g.drawImage(backSW, (int) tableposition[2][0].getX(),
					(int) tableposition[2][0].getY(), sh);
		if (faceup[2][1] != null)
			faceup[2][1].drawSideWays(tableposition[2][1]);
		else if (carddowncount[2] >= 2)
			g.drawImage(backSW, (int) tableposition[2][1].getX(),
					(int) tableposition[2][1].getY(), sh);
		if (faceup[2][2] != null)
			faceup[2][2].drawSideWays(tableposition[2][2]);
		else if (carddowncount[2] >= 1)
			g.drawImage(backSW, (int) tableposition[2][2].getX(),
					(int) tableposition[2][2].getY(), sh);

		// drawing pile
		if (pile[0] != null) {
			// determining how many cards of the same value are ontop of each
			// other
			int top = 0;
			if (nine == true && pile[0].getValue() == 9) {
				top = 1;
				if (pile[1] != null)
					if (pile[1].getValue() == 9) {
						top = 2;
						if (pile[2] != null)
							if (pile[2].getValue() == 9)
								top = 3;
					}
			}
			int samecount = 1;
			for (int n = top + 1; n < top + 4; n++) {
				if (pile[n] == null)
					break;
				if (pile[n].getValue() == pile[top].getValue())
					samecount++;
				else
					break;
			}
			if (samecount == 1) {// one of a kind
				if (pile[top] != null)
					pile[top].drawCard(centre1);
			} else if (samecount == 2) {// 2 of a kind
				pile[top + 1].drawCard2((int) centre1.getX(),
						(int) centre1.getY() - 10);
				pile[top].drawCard2((int) centre1.getX(),
						(int) centre1.getY() + 10);
			} else if (samecount >= 3) {// 3 of a kind
				pile[top + 2].drawCard2((int) centre1.getX(),
						(int) centre1.getY() - 20);
				pile[top + 1].drawCard2((int) centre1.getX(),
						(int) centre1.getY());
				pile[top].drawCard2((int) centre1.getX(),
						(int) centre1.getY() + 20);
			}
			if (nine == true && pile[0].getValue() == 9)
				if (top == 1)// one nine
					pile[0].drawSideWays2((int) centre1.getX() - 15,
							(int) centre1.getY() + 40);
			if (top == 2) {// 2 nines
				pile[1].drawSideWays2((int) centre1.getX() - 15,
						(int) centre1.getY() + 40);
				pile[0].drawSideWays2((int) centre1.getX() - 15,
						(int) centre1.getY() + 50);
			}
			if (top == 3) {// 3 nines
				pile[2].drawSideWays2((int) centre1.getX() - 15,
						(int) centre1.getY() + 40);
				pile[1].drawSideWays2((int) centre1.getX() - 15,
						(int) centre1.getY() + 50);
				pile[0].drawSideWays2((int) centre1.getX() - 15,
						(int) centre1.getY() + 60);
			}
		} else if (burnt) {
			g.drawImage(burntPic, 130, 190, sh);
			burnt = false;
		}
		g.drawImage(pointer[whosturn], (int) pointerpoints[whosturn].getX(),
				(int) pointerpoints[whosturn].getY(), sh);
		sh.repaint();
	}

	public void cardSelection(int cardno) {
		Card card;
		String command;
		if (hand.getCard(0) == null) {// if player only has cards on table
			if (hand.isFaceUp()) { // if cards still faceup on table
				card = hand.getFaceUp(cardno);
				command = "turn:faceup:";
				if (isValidCard(card, command))
					for (int i = 0; i < 3; i++)
						if (hand.getFaceUp(i) != null)
							if (hand.getFaceUp(i).getNumber() == card
									.getNumber()) {
								hand.removeFaceUp(i);
								break;
							}
			} else {// if only cards down
				card = hand.getFaceDown(cardno);
				command = "turn:facedown:";
				if (isValidCard(card, command))
					hand.removeFaceDown(cardno);
				else {// player must pick up the pile if not valide
					hand.addCard(hand.getFaceDown(cardno));
					sendCommand("turn:facedown:pickup:"
							+ hand.getFaceDown(cardno).getNumber() + ":");
					sh.addMsg("The card you played was a "
							+ hand.getFaceDown(cardno).getStringValue()
							+ " you had to pick up the pile");
					for (int n = 0; n < 52; n++) {
						if (pile[n] == null)
							break;
						hand.addCard(pile[n]);
						pile[n] = null;
					}
					hand.removeFaceDown(cardno);
					sh.setmyTurn(false);
					nextTurn();
				}
			}
		} else {// if player still has cards in hand
			card = hand.getCard(cardno);
			command = "turn:";
			if (isValidCard(card, command))
				for (int n = 0; n < hand.length() - 1; n++)
					if (card.getNumber() == hand.getCard(n).getNumber()) {
						hand.removeCard(n);
						break;
					}
		}
		if (deck <= 0 || hand.length() > 3)
			displayTable();
	}

	private boolean isValidCard(Card card, String command) {
		int top = 0;
		boolean multi = false;
		if (hand.getCard(0) != null)
			multi = checkformulti(card);
		else if (hand.isFaceUp())
			multi = checkformultiFaceUp(card);

		if (multi)
			return true;

		if (card.getValue() == 2) {// 2 can be played at anytime
			cardAccepted(card, command);
			return true;
		} else if (card.getValue() == 10 || fourOfAKind(card) == true) {// pile
																		// is
																		// burn
																		// and
																		// its
																		// players
																		// turn
																		// again
			burnt = true;
			for (int n = 0; n < 51; n++)
				pile[n] = null;
			sendCommand(command + card.getNumber() + ":");
			sh.addMsg("You have burnt the pile, its your turn again");
			return true;
		} else if (pile[0] == null) {
			cardAccepted(card, command);
			return true;
		} else if (nine == true && card.getValue() == 9) {
			cardAccepted(card, command);
			return true;
		}
		if (nine == true && pile[0].getValue() == 9) {
			for (int i = 0; i < 52; i++) {
				if (pile[i] == null) {
					cardAccepted(card, command);
					return true;
				}
				if (pile[i].getValue() == 9)
					top++;
				else
					break;
			}

		}
		if (seven == true && pile[top].getValue() == 7) {
			if (card.getValue() >= 7) {
				sh.addMsg("You Must Play Less Than a Seven");
				return false;
			} else {
				cardAccepted(card, command);
				return true;
			}
		}
		if (pile[top].getValue() <= card.getValue()) {
			cardAccepted(card, command);
			return true;
		}
		if (hand.isFaceUp() == true || hand.length() > 1)
			sh.addMsg("You can't play a " + card.getStringValue()
					+ " please select another card");
		return false;
	}

	private boolean checkformulti(Card card) {
		// checking if card selection is valid
		if (pile[0] != null) {
			if (nine == true && pile[0].getValue() == 9) {
				int count = 0;// determining the number of nines on top of pile
				for (int i = 0; i < 52; i++) {
					if (pile[i] == null)
						break;
					if (pile[i].getValue() == 9)
						count++;
					else
						break;
				}
				if (pile[count] != null) {
					if (card.getValue() == 9) {
						// do nothing as valid card
					} else if (seven == true && pile[count].getValue() == 7) {
						if (card.getValue() >= 7)
							return false;
					} else if (!(card.getValue() == 2 || card.getValue() == 10 || card
							.getValue() >= pile[count].getValue()))
						return false;
				}
			} else if (card.getValue() == 9 && nine == true) {
				// do nothing as valid card
			} else if (seven == true && pile[0].getValue() == 7) {
				if (card.getValue() >= 7)
					return false;
			} else if (!(card.getValue() == 2 || card.getValue() == 10 || card
					.getValue() >= pile[0].getValue()))
				return false;
		}

		// checking how many card of the same value as card played are in
		// players hand
		int amountinhand = 0;
		for (int n = 0; n < hand.length(); n++) {
			if (hand.getCard(n) == null)
				break;
			if (hand.getCard(n).getValue() == card.getValue())
				amountinhand++;
		}
		if (amountinhand <= 1)
			return false;
		MultiCardD dialog = new MultiCardD(sh, amountinhand);
		int numbertoplay = dialog.getChoice();
		if (numbertoplay <= 1)
			return false;
		String command = "turn:multi:" + numbertoplay + ":" + card.getNumber()
				+ ":";
		addcardtopile(card);
		numbertoplay--;
		int toberemovedcount = 0;
		int toberemoved[] = new int[3];
		for (int n = 0; n < 3; n++)
			toberemoved[n] = -1;
		for (int n = 0; n < hand.length() - 1; n++) {
			if (hand.getCard(n) == null)
				break;
			if (numbertoplay <= 0)
				break;
			if (card.getValue() == hand.getCard(n).getValue()
					&& card.getNumber() != hand.getCard(n).getNumber()) {
				command = command.concat(hand.getCard(n).getNumber() + ":");
				addcardtopile(hand.getCard(n));
				// storing which card are to be removed
				toberemoved[toberemovedcount] = hand.getCard(n).getNumber();
				toberemovedcount++;
				numbertoplay--;
			}
		}
		// removing card from hand
		for (int n = 0; n < 3; n++) {
			if (toberemoved[n] == -1)
				break;
			for (int i = 0; i < hand.length() - 1; i++)
				if (hand.getCard(i).getNumber() == toberemoved[n]) {
					hand.removeCard(i);
					break;
				}
		}
		// sending command
		sendCommand(command);
		// checking for 4 of a kind
		if (fourOfAKind(pile[3]) || pile[0].getValue() == 10) {
			burnt = true;
			for (int n = 0; n < 51; n++)
				pile[n] = null;
			sh.addMsg("You burn the pile is your turn again");
		} else {
			sh.setmyTurn(false);
			nextTurn();
		}
		return true;
	}

	private boolean checkformultiFaceUp(Card card) {
		// checking if card selection is valid
		if (pile[0] != null) {
			if (card.getValue() == 9 && nine == true) {
				// do nothing as valid card
			} else if (card.getValue() == 10 || card.getValue() == 2) {
				// do nothing as valid card
			} else if (nine == true && pile[0].getValue() == 9) {
				int count = 0;// determining the number of nines on top of pile
				for (int i = 0; i < 52; i++) {
					if (pile[i] == null)
						break;
					if (pile[i].getValue() == 9)
						count++;
					else
						break;
				}
				if (pile[count] != null) {
					if (seven == true && pile[count].getValue() == 7) {
						if (card.getValue() >= 7)
							return false;
					} else if (!(card.getValue() == 2 || card.getValue() == 10 || card
							.getValue() >= pile[count].getValue()))
						return false;
				}
			} else if (seven == true && pile[0].getValue() == 7) {
				if (card.getValue() >= 7)
					return false;
			} else if (!(card.getValue() == 2 || card.getValue() == 10 || card
					.getValue() >= pile[0].getValue()))
				return false;
		}

		// checking how many card of the same value as card played are in
		// players hand
		int amountinhand = 0;
		for (int n = 0; n < 3; n++) {
			if (hand.getFaceUp(n) != null)
				if (hand.getFaceUp(n).getValue() == card.getValue())
					amountinhand++;
		}
		if (amountinhand <= 1)
			return false;
		MultiCardD dialog = new MultiCardD(sh, amountinhand);
		int numbertoplay = dialog.getChoice();
		if (numbertoplay <= 1)
			return false;
		String command = "turn:faceup:multi:" + numbertoplay + ":"
				+ card.getNumber() + ":";
		addcardtopile(card);
		numbertoplay--;
		int toberemovedcount = 0;
		int toberemoved[] = new int[3];
		for (int n = 0; n < 3; n++)
			toberemoved[n] = -1;
		for (int n = 0; n < 3; n++)
			if (hand.getFaceUp(n) != null) {
				if (numbertoplay <= 0)
					break;
				if (card.getValue() == hand.getFaceUp(n).getValue()
						&& card.getNumber() != hand.getFaceUp(n).getNumber()) {
					command = command.concat(hand.getFaceUp(n).getNumber()
							+ ":");
					addcardtopile(hand.getFaceUp(n));
					// storing which card are to be removed
					toberemoved[toberemovedcount] = hand.getFaceUp(n)
							.getNumber();
					toberemovedcount++;
					numbertoplay--;
				}
			}
		// removing card from hand
		for (int n = 0; n < 3; n++) {
			if (toberemoved[n] == -1)
				break;
			for (int i = 0; i < 3; i++)
				if (hand.getFaceUp(i) != null)
					if (hand.getFaceUp(i).getNumber() == toberemoved[n]) {
						hand.removeFaceUp(i);
						break;
					}
		}
		// sending command
		sendCommand(command);
		// checking for 4 of a kind
		if (fourOfAKind(pile[3]) || pile[0].getValue() == 10) {
			burnt = true;
			for (int n = 0; n < 51; n++)
				pile[n] = null;
			sh.addMsg("You burn the pile is your turn again");
		} else {
			sh.setmyTurn(false);
			nextTurn();
		}
		return true;
	}

	private void addcardtopile(Card card) {
		// adding card to pile
		for (int i = 51; i > 0; i--)
			pile[i] = pile[i - 1];
		pile[0] = card;
	}

	private void cardAccepted(Card card, String command) {
		sendCommand(command + card.getNumber() + ":");
		// adding card to pile
		for (int n = 51; n > 0; n--)
			pile[n] = pile[n - 1];
		pile[0] = card;
		sh.setmyTurn(false);
		nextTurn();
	}

	private int pilelength() {
		int cardCount = 0;
		for (int n = 0; n < 52; n++) {
			if (pile[n] == null)
				break;
			cardCount++;
		}
		return cardCount;
	}

	class WaitforMsg implements Runnable {

		Thread wt; // Wait Thread

		WaitforMsg() {
			wt = new Thread(this, "Wait");
			wt.start(); // Starting thread
		}

		public void run() {
			do {
				String otherplayermsg = "Message Error";
				try {
					otherplayermsg = in.readLine();
				} catch (IOException e) {
					sh.addMsg("Read Error: " + e);
					sh.addMsg("Server Disconnection");
					listen = false;
				}

				if (otherplayermsg == null)
					endConnection();
				else if (otherplayermsg.equals("end:"))
					endConnection();
				else if (listen) {
					// sh.addMsg("Msg: " +
					// otherplayermsg);//------------------------------------msg
					// from server

					int commandlength = 0;
					// decode message and perform function required
					for (int n = 0; n < otherplayermsg.length(); n++) {
						char extract = otherplayermsg.charAt(n);
						if (extract == (':')) {
							commandlength = n;
							break;
						}
					}
					String command = otherplayermsg.substring(0, commandlength);

					if (command.equals("deal"))
						deal(otherplayermsg, commandlength);

					if (command.equals("otherdetails"))
						otherdetails(otherplayermsg, commandlength);

					if (command.equals("yourturn"))
						yourturn();

					if (command.equals("getcard"))
						getcard(otherplayermsg, commandlength);

					if (command.equals("othersturn"))
						othersturn(otherplayermsg, commandlength);

					if (command.equals("msg"))
						sh.addMsg(otherplayermsg.substring(commandlength,
								otherplayermsg.length()));

					if (command.equals("out"))
						out(otherplayermsg, commandlength);

					if (command.equals("otherout"))
						otherout(otherplayermsg, commandlength);

					if (command.equals("lost"))
						lost(otherplayermsg, commandlength);

					if (command.equals("reset"))
						reset();

				}
			} while (listen);
		}

		private void reset() {
			swapdone = false;
			for (int n = 0; n < 4; n++) {
				// setting scoreboard if game finishes early
				if (n < 3) {
					if (outofgame[n] == false)
						score.addScore(othernames[n], position);
				} else {
					if (outofgame[n] == false)
						score.addScore(playersName, position);
				}
				outofgame[n] = false;
			}
			position = 1;
			for (int n = 0; n < 3; n++)
				if (othernames[n].equals(servername))
					whosturn = n;
			hand.removeAll();
			for (int n = 0; n < 3; n++) {
				for (int i = 0; i < 3; i++)
					faceup[n][i] = null;
				carddowncount[n] = 3;
				cardcount[n] = 3;
				deck = 16;
			}
			for (int n = 0; n < 52; n++)
				pile[n] = null;
		}

		// msg telling player they are out of the game and what posititon they
		// came
		private void out(String otherplayermsg, int commandlength) {

			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String positionString = otherplayermsg.substring(commandlength + 1,
					varlength);
			int playerPosition = 0;
			try {
				playerPosition = Integer.parseInt(positionString);
			} catch (NumberFormatException b) {
				sh.addMsg("Otherplayer - out -  variable to Int error: " + b);
			}

			boolean gameover = false;
			if (playerPosition == 0)
				sh.addMsg("Position Error");
			if (playerPosition == 1)
				sh.addMsg("Well done you have won the game your the first out !!");
			else if (playerPosition == 2)
				sh.addMsg("You've done alright you the second out of the game");
			else if (playerPosition == 3)
				sh.addMsg("Just made it, congrats your not a ShitHead !");
			else if (playerPosition == 4) {
				sh.addMsg("You Lost ShitHead !!!");
				gameover = true;
			}

			outofgame[3] = true;

			score.addScore(playersName, position);

			if (playerPosition == 4)
				score.display();
			else
				position++;

			if (whosturn == 3 && !gameover) {
				nextTurn();
				displayTable();
			}

		}

		// msg stating another player is out of the game
		private void otherout(String otherplayermsg, int commandlength) {

			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String name = otherplayermsg
					.substring(commandlength + 1, varlength);

			sh.addMsg(name + " is out of the game");

			score.addScore(name, position);
			position++;

			for (int n = 0; n < 3; n++)
				if (othernames[n].equals(name)) {
					outofgame[n] = true;
					if (whosturn == n) {
						nextTurn();
						displayTable();
					}
				}
		}

		// telling player who lost.
		private void lost(String otherplayermsg, int commandlength) {

			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String name = otherplayermsg
					.substring(commandlength + 1, varlength);

			sh.addMsg(name + " is the ShitHead");
			sh.addMsg("Game Over");

			score.addScore(name, 4);

			for (int n = 0; n < 3; n++)
				if (othernames[n].equals(name))
					outofgame[n] = true;

			score.display();
		}

		/*--------------------------------
		 *   Othersturn msg format
		 *   command: - 'otherplayer'
		 *   name: players name
		 *   cardno:(move) - 'pickup'
		 *                 - 'burn'
		 *                 - 'faceup'   - cardno2:  - a card number
		 *                                          - 'multi' - numberplayed - up to 3 card numbers
		 *                 - 'facedown' - cardno2:  - 'pickup'
		 *                                          - a card number
		 *                 -  'multi' - numberplayed - up to 4 card numbers
		 *                 - a card number
		 *-------------------------------*/
		private void othersturn(String otherplayermsg, int commandlength) {
			boolean burn = false;
			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String name = otherplayermsg
					.substring(commandlength + 1, varlength);
			int varlength2 = 0;
			for (int n = varlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength2 = n;
					break;
				}
			}
			String cardno = otherplayermsg.substring(varlength + 1, varlength2);

			// determining which player just had a turn
			int playernumber = 0;
			for (int n = 0; n < 3; n++)
				if (name.equals(othernames[n])) {
					playernumber = n;
					break;
				}

			if (cardno.equals("pickup")) {// other players picks up pile
				cardcount[playernumber] = cardcount[playernumber]
						+ pilelength();
				for (int n = 0; n < 52; n++)
					pile[n] = null;
				sh.addMsg(othernames[playernumber] + " picked up the pile");
			} else if (cardno.equals("burn")) {// other player burns the pile
				burnt = true;
				burn = true;
				// removing cards from pile
				sh.addMsg(name + " burnt the pile.");
				for (int n = 0; n < 51; n++)
					pile[n] = null;
				if (deck == 0 || cardcount[playernumber] > 3) {
					if (cardcount[playernumber] > 0)
						cardcount[playernumber]--;
				} else
					deck--;
			} else if (cardno.equals("faceup")) {// otherplayer plays a faceup
													// card
				int varlength3 = 0;
				for (int n = varlength2 + 1; n < otherplayermsg.length(); n++) {
					char extract = otherplayermsg.charAt(n);
					if (extract == (':')) {
						varlength3 = n;
						break;
					}
				}
				String cardno2 = otherplayermsg.substring(varlength2 + 1,
						varlength3);
				if (cardno2.equals("multi")) {
					burn = faceupmulti(otherplayermsg, varlength3, playernumber);
				} else {
					try {
						Card card = new Card(Integer.parseInt(cardno2),
								cardspic, sh, g);
						// adding card to pile
						for (int n = 51; n > 0; n--)
							pile[n] = pile[n - 1];
						pile[0] = card;
						// burning pile if a 10 is played
						if (pile[0].getValue() == 10
								|| fourOfAKind(pile[3]) == true) {
							burnt = true;
							burn = true;
							// removing cards from pile
							sh.addMsg(name + " burnt the pile.");
							for (int n = 0; n < 51; n++)
								pile[n] = null;
						}
						// removing card from table
						for (int n = 0; n < 3; n++)
							if (faceup[playernumber][n] != null)
								if (faceup[playernumber][n].getNumber() == card
										.getNumber()) {
									faceup[playernumber][n] = null;
									break;
								}
					} catch (NumberFormatException b) {
						sh.addMsg("Otherplayer - variable to Int error: " + b);
					}
				}
			} else if (cardno.equals("facedown")) {// if player plays one of
													// there face down cards
				int varlength3 = 0;
				for (int n = varlength2 + 1; n < otherplayermsg.length(); n++) {
					char extract = otherplayermsg.charAt(n);
					if (extract == (':')) {
						varlength3 = n;
						break;
					}
				}
				String cardno2 = otherplayermsg.substring(varlength2 + 1,
						varlength3);
				if (cardno2.equals("pickup")) {
					for (int n = varlength3 + 1; n < otherplayermsg.length(); n++) {
						char extract = otherplayermsg.charAt(n);
						if (extract == (':')) {
							varlength2 = n;
							break;
						}
					}
					String cardplayed = otherplayermsg.substring(
							varlength3 + 1, varlength2);
					int numPlayed = 0;
					try {
						numPlayed = Integer.parseInt(cardplayed);
					} catch (NumberFormatException b) {
						sh.addMsg("processTurn - facedown pickup - variable to Int error: "
								+ b);
					}
					cardcount[playernumber] = cardcount[playernumber]
							+ pilelength() + 1;
					for (int n = 0; n < 52; n++)
						pile[n] = null;
					sh.addMsg(othernames[playernumber] + " played a "
							+ Card.getCardStringValue(numPlayed)
							+ " and had to picked up the pile");
				} else {
					try {
						Card card = new Card(Integer.parseInt(cardno2),
								cardspic, sh, g);
						for (int n = 51; n > 0; n--)
							pile[n] = pile[n - 1];
						pile[0] = card;
						// burning pile if a 10 is played
						if (pile[0].getValue() == 10
								|| fourOfAKind(pile[3]) == true) {
							burnt = true;
							burn = true;
							// removing cards from pile
							sh.addMsg(name + " burnt the pile.");
							for (int n = 0; n < 51; n++)
								pile[n] = null;
						}
					} catch (NumberFormatException b) {
						sh.addMsg("Otherplayer - variable to Int error: " + b);
					}
				}
				carddowncount[playernumber]--;
			} else if (cardno.equals("multi")) {// if more than 1 card is played
												// at a time
				// determining how many card where played
				int varlength3 = 0;
				for (int n = varlength2 + 1; n < otherplayermsg.length(); n++) {
					char extract = otherplayermsg.charAt(n);
					if (extract == (':')) {
						varlength3 = n;
						break;
					}
				}
				String numPlayedString = otherplayermsg.substring(
						varlength2 + 1, varlength3);
				// converting string to int for processing
				int numPlayed = 0;
				try {
					numPlayed = Integer.parseInt(numPlayedString);
				} catch (NumberFormatException b) {
					sh.addMsg("processTurn - multi - variable to Int error: "
							+ b);
				}
				for (int n = 0; n < numPlayed; n++) {
					varlength2 = varlength3;
					// determining how many card where played
					varlength3 = 0;
					for (int i = varlength2 + 1; i < otherplayermsg.length(); i++) {
						char extract = otherplayermsg.charAt(i);
						if (extract == (':')) {
							varlength3 = i;
							break;
						}
					}
					String cardnoString = otherplayermsg.substring(
							varlength2 + 1, varlength3);
					// converting string to int for processing
					try {
						Card card = new Card(Integer.parseInt(cardnoString),
								cardspic, sh, g);
						addcardtopile(card);
					} catch (NumberFormatException b) {
						sh.addMsg("processTurn - multi - variable to Int error: "
								+ b);
					}

					if (deck == 0 || cardcount[playernumber] > 3) {
						if (cardcount[playernumber] > 0)
							cardcount[playernumber]--;
					} else
						deck--;
				}

				// burning pile if a 10 is played or 4 of a kind
				if (pile[0].getValue() == 10 || fourOfAKind(pile[3]) == true) {
					burnt = true;
					burn = true;
					// removing cards from pile
					sh.addMsg(name + " burnt the pile.");
					for (int i = 0; i < 51; i++)
						pile[i] = null;
				}

			} else {
				// adding card to pile
				try {
					Card card = new Card(Integer.parseInt(cardno), cardspic,
							sh, g);
					for (int n = 51; n > 0; n--)
						pile[n] = pile[n - 1];
					pile[0] = card;
					// burning pile if a 10 is played
					if (pile[0].getValue() == 10
							|| fourOfAKind(pile[3]) == true) {
						burn = true;
						burnt = true;
						// removing cards from pile
						sh.addMsg(name + " burnt the pile.");
						for (int n = 0; n < 51; n++)
							pile[n] = null;
					}
				} catch (NumberFormatException b) {
					sh.addMsg("Otherplayer else - variable to Int error: " + b);
				}
				if (deck == 0 || cardcount[playernumber] > 3) {
					if (cardcount[playernumber] > 0)
						cardcount[playernumber]--;
				} else
					deck--;
			}
			if (!burn)
				nextTurn();
			displayTable();
		}

		private boolean faceupmulti(String otherplayermsg, int varlength2,
				int playernumber) {
			boolean burn = false;
			// determining how many card where played
			int varlength3 = 0;
			for (int n = varlength2 + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength3 = n;
					break;
				}
			}
			String numPlayedString = otherplayermsg.substring(varlength2 + 1,
					varlength3);
			// converting string to int for processing
			int numPlayed = 0;
			try {
				numPlayed = Integer.parseInt(numPlayedString);
			} catch (NumberFormatException b) {
				sh.addMsg("processTurn - multi face up - variable to Int error: "
						+ b);
			}
			for (int n = 0; n < numPlayed; n++) {
				varlength2 = varlength3;
				// determining how many card where played
				varlength3 = 0;
				for (int i = varlength2 + 1; i < otherplayermsg.length(); i++) {
					char extract = otherplayermsg.charAt(i);
					if (extract == (':')) {
						varlength3 = i;
						break;
					}
				}
				String cardnoString = otherplayermsg.substring(varlength2 + 1,
						varlength3);
				// converting string to int for processing
				try {
					Card card = new Card(Integer.parseInt(cardnoString),
							cardspic, sh, g);
					addcardtopile(card);

					for (int i = 0; i < 3; i++)
						if (faceup[playernumber][i] != null)
							if (faceup[playernumber][i].getNumber() == card
									.getNumber()) {
								faceup[playernumber][i] = null;
								break;
							}
				} catch (NumberFormatException b) {
					sh.addMsg("processTurn - multi - variable to Int error: "
							+ b);
				}

			}
			// burning pile if a 10 is played or 4 of a kind
			if (pile[0].getValue() == 10 || fourOfAKind(pile[3]) == true) {
				burnt = true;
				burn = true;
				// removing cards from pile
				sh.addMsg(othernames[playernumber] + " burnt the pile.");
				for (int i = 0; i < 51; i++)
					pile[i] = null;
			}
			return burn;
		}

		private void yourturn() {
			// making sure turn arrow is pointed correctly
			if (whosturn != 3) {
				whosturn = 3;
				displayTable();
			}

			int top = 0;
			// testing is player has a card they can play
			if (pile[0] != null) {
				boolean canplay = false;
				if (hand.getCard(0) == null) {// if player only has card on the
												// table
					if (hand.isFaceUp())// if player has faceup card on the
										// table
					{
						for (int n = 0; n < 3; n++) {
							if (hand.getFaceUp(n) != null) {
								if (nine == true && pile[0].getValue() == 9) {
									top = 0;
									for (int i = 0; i < 52; i++) {
										if (pile[i] == null) {
											canplay = true;
											break;
										}
										if (pile[i].getValue() == 9)
											top++;
										else
											break;
									}
								}
								if (canplay)
									break;
								if (seven == true && pile[top].getValue() == 7
										&& hand.getFaceUp(n).getValue() < 7) {
									canplay = true;
									break;
								} else if (hand.getFaceUp(n).getValue() == 2
										|| hand.getFaceUp(n).getValue() == 10) {
									canplay = true;
									break;
								} else if (nine == true
										&& hand.getFaceUp(n).getValue() == 9) {
									canplay = true;
									break;
								} else if (seven != true
										|| pile[top].getValue() != 7) {
									if (pile[top].getValue() <= hand.getFaceUp(
											n).getValue()) {
										canplay = true;
										break;
									}
								}
							}
						}
					} else
						// if player only has facedown cards
						canplay = true;
				} else {
					for (int n = 0; n < hand.length() - 1; n++) {
						if (hand.getCard(n) == null)
							break;
						if (nine == true && pile[0].getValue() == 9) {
							top = 0;
							for (int i = 0; i < 52; i++) {
								if (pile[i] == null) {
									canplay = true;
									break;
								}
								if (pile[i].getValue() == 9)
									top++;
								else
									break;
							}

						}
						if (canplay)
							break;
						if (hand.getCard(n).getValue() == 2
								|| hand.getCard(n).getValue() == 10) {
							canplay = true;
							break;
						}
						if (nine == true && hand.getCard(n).getValue() == 9) {
							canplay = true;
							break;
						}
						if (seven == true && pile[top].getValue() == 7
								&& hand.getCard(n).getValue() < 7) {
							canplay = true;
							break;
						} else if (seven != true || pile[top].getValue() != 7) {
							if (pile[top].getValue() <= hand.getCard(n)
									.getValue()) {
								canplay = true;
								break;
							}
						}
					}
				}
				if (canplay) {
					// sh.addMsg("Its Your Turn");
					sh.setmyTurn(true);
				} else {// cant play then must pick up the pile
					sh.addMsg("The card played was a "
							+ pile[top].getStringValue()
							+ " you had to pick up the pile");
					for (int n = 0; n < 52; n++) {
						if (pile[n] == null)
							break;
						hand.addCard(pile[n]);
						pile[n] = null;
					}
					sendCommand("turn:pickup:");
					nextTurn();
					displayTable();
				}
			} else {
				// sh.addMsg("Its Your Turn");
				sh.setmyTurn(true);
			}
		}

		private void getcard(String otherplayermsg, int commandlength) {
			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String variable = otherplayermsg.substring(commandlength + 1,
					varlength);

			// Adding card to hand
			try {
				Card card = new Card(Integer.parseInt(variable), cardspic, sh,
						g);
				hand.addCard(card);
			} catch (NumberFormatException b) {
				sh.addMsg("Deal - variable to Int error: " + b);
			}
			deck--;
			displayTable();
		}

		private void deal(String otherplayermsg, int commandlength) {
			// decode variable that came with message
			int varlength = 0;
			for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
				char extract = otherplayermsg.charAt(n);
				if (extract == (':')) {
					varlength = n;
					break;
				}
			}
			String variable = otherplayermsg.substring(commandlength + 1,
					varlength);

			// Adding card to deck
			try {
				Card card = new Card(Integer.parseInt(variable), cardspic, sh,
						g);
				hand.deal(card);
			} catch (NumberFormatException b) {
				sh.addMsg("Deal - variable to Int error: " + b);
			}

		}

		// getting the details of other players
		private void otherdetails(String otherplayermsg, int commandlength) {
			// decode variable that came with message
			String variables[] = new String[12];
			for (int i = 0; i < 12; i++) {
				int varlength = 0;
				for (int n = commandlength + 1; n < otherplayermsg.length(); n++) {
					char extract = otherplayermsg.charAt(n);
					if (extract == (':')) {
						varlength = n;
						break;
					}
				}
				variables[i] = otherplayermsg.substring(commandlength + 1,
						varlength);
				commandlength = varlength;
			}

			// adding other players details to storage arrays
			for (int n = 0; n < 3; n++) {
				othernames[n] = variables[4 * n];
				score.addName(variables[4 * n]);
				// sh.addMsg("Test - othername " + othernames[n] + " severname "
				// + servername);//--------------------TEST
				if (othernames[n].equals(servername))
					whosturn = n;
				cardcount[n] = 3;
				carddowncount[n] = 3;
				try {
					for (int i = 0; i < 3; i++) {
						Card card = new Card(Integer.parseInt(variables[4 * n
								+ 1 + i]), cardspic, sh, g);
						faceup[n][i] = card;
					}
				} catch (NumberFormatException b) {
					sh.addMsg("otherdetails - variable to Int error: " + b);
				}
			}
			deck = 16;
			if (fastgame)
				deck = 0;
			displayTable();
			if (swap == true && swapdone == false) {// if performing card swap
				Card inhand[] = new Card[3];
				Card ontable[] = new Card[3];
				for (int n = 0; n < 3; n++) {
					inhand[n] = hand.getCard(n);
					ontable[n] = hand.getFaceUp(n);
				}
				SwapD swapD = new SwapD(sh, inhand, ontable);
				if (swapD.display()) {
					inhand = swapD.getInHand();
					ontable = swapD.getOnTable();
					hand.swap(inhand, ontable);
					displayTable();
				}
				sendCommand("swap:" + inhand[0].getNumber() + ":"
						+ inhand[1].getNumber() + ":" + inhand[2].getNumber()
						+ ":" + ontable[0].getNumber() + ":"
						+ ontable[1].getNumber() + ":" + ontable[2].getNumber()
						+ ":");
				swapdone = true;
			}
		}
	}

}